package org.batatasframework.support.attribute;

import java.util.HashMap;
import java.util.Map;

import org.batatasframework.support.database.DatabaseType;
import org.batatasframework.support.database.IdentifyTableBase;
import org.batatasframework.support.database.IdentifyTableGenerator;
import org.batatasframework.support.database.TableInfo;
import org.batatasframework.support.database.metadatas.AbstractFieldMetadata;
import org.batatasframework.support.database.metadatas.AbstractTableMetadata;
import org.batatasframework.support.database.metadatas.FieldMetadata;
import org.batatasframework.support.database.metadatas.TableMetadata;
import org.batatasframework.support.database.spi.FieldElementBuilder;
import org.batatasframework.support.database.sql.TableInstance;
import org.batatasframework.support.database.sql.TableRuntimeMaster;
import org.batatasframework.support.database.sql.field.AbstractFieldElement;
import org.batatasframework.support.database.sql.field.FieldElement;
import org.batatasframework.support.type.JavaType;

import cn.bonoon.kernel.util.StringHelper;

public class TableMetadataAttributeImpl extends AbstractTableMetadata<FieldMetadataAttribute> implements TableMetadataAttribute{

	private final TableMetadata mainTableMetadata;
	/** 可以自定义，但要是唯一值，创建临时表时，这个可以是临时表的名字。 */
	private final String key;
	/** 属性表的中文名，菜单或表头可以直接引用的 */
	private String title;
	private int version;
	
	/** see {@link #getSeparateField()} */
	@Deprecated
	private String separateField;
	
	private String mainField;
	
	private IdentifyTableGenerator defaultTableGenerator;
	
	private final String[] attributeTables;
	
	private final Map<String, String[]> attributeFilters = new HashMap<>();
	
	public TableMetadataAttributeImpl(
			TableMetadata mainTableMetadata, 
			String key, 
			String[] attributeTables) {
		this.mainTableMetadata = mainTableMetadata;
		this.attributeTables = attributeTables;
		
		this.key = key;
		this.mainField = mainTableMetadata.getPrimaryKey();
	}
	
	public void filter(String name, String...filters){
		attributeFilters.put(name, filters);
	}

	@Override
	public TableMetadata getTableMetadata() {
		return this;
	}
	
	public String getKey() {
		return key;
	}
	
	@Override
	public String getMainField() {
		return mainField;
	}
	
	public void setMainField(String mainField) {
		if(StringHelper.isNotEmpty(mainField))
			this.mainField = mainField;
	}
	
	@Override
	protected FieldMetadata _get(String key) {
		FieldMetadata fieldMetadata = super._get(key);
		
		/*
		 * 在定义的指标表里，如果要查找某一个字段，则除了查询是否是指标项外，
		 * 还要查询是否是主表的字段；
		 * 
		 * 是相当于把主表和属性表联合起来当一个大表来看待。
		 */
		if(fieldMetadata == null) {
			fieldMetadata = mainTableMetadata.getOrNull(key);
		}
		return fieldMetadata;
	}
	
	@Override
	public TableInfo getTableInfo() {
		return mainTableMetadata.getTableInfo();
	}

	@Override
	public String getTableName() {
		return mainTableMetadata.getTableName();
	}

	@Override
	public String getPrimaryKey() {
		return mainTableMetadata.getPrimaryKey();
	}

	public String getTitle() {
		return title;
	}
	
	public int getVersion() {
		return version;
	}

	/**
	 * <pre>
	 * 如果指标表使用分表的话，这个字段指向的是用于区分分表的主表的字段。
	 * 如：separateField=cityid，表示按城市ID这个字段来进行分表存储
	 * 
	 * 如果指标表只有一个表，则这个字段为null
	 * </pre>
	 */
	@Override
	public String getSeparateField() {
		return separateField;
	}
	
	public void setVersion(int version) {
		this.version = version;
	}
	
	public void setTitle(String title) {
		if(StringHelper.isNotEmpty(title))
			this.title = title;
	}
	
	/** see {@link #getSeparateField()} */
	public void setSeparateField(String separateField) {
		if(StringHelper.isNotEmpty(separateField))
			this.separateField = separateField;
	}

	public IdentifyTableGenerator getDefaultTableGenerator() {
		return defaultTableGenerator;
	}

	public void setDefaultTableGenerator(IdentifyTableGenerator defaultTableGenerator) {
		this.defaultTableGenerator = defaultTableGenerator;
	}
	
	public InternalFieldMetadataAttribute createField(String name){
		return new InternalFieldMetadataAttribute(this, name);
	}
	
	
	class InternalFieldMetadataAttribute extends AbstractFieldMetadata<TableMetadataAttribute>
		implements FieldMetadataAttribute, FieldElementBuilder{
	
		/**
		 * <pre>
		 * 指标的编码，如：A1，B2a等
		 * 这个编码用于存入数据库，必须是唯一的值
		 * 
		 * 原来的code字段
		 * 
		 * 相当于字段名，这个名称定义后就不能再改的
		 * </pre>
		 */
		protected final String name;
	
		private InternalFieldMetadataAttribute(TableMetadataAttribute attributeContext, String name){
			super(attributeContext);
			this.name = name;
		}
	
		/**
		 * 完整的定义，包括：编码+名称+单位
		 */
		protected String headTitle;
		
		/**
		 * 在某些情况下，已经存储在数据库的code不一定就是所需要的指标的值；
		 * 如，本来定义A1为性别的，但后来需要调整A1为身份证，在这种情况下，不能直接修改
		 * code的值，因为数据库已经存在，所以只能对编码进行另外的指定
		 * 正常情况下code与codeName相等
		 */
		protected String codeName;
		
		/**
		 * 显示在文本框上的提示信息，即鼠标移上去出现的提示信息
		 */
		protected String tooltip;
		
		/**
		 * <pre>
		 * 数字的单位，如：个、元、万元等
		 * 一 般会以"()"的格式追加在后面，如：
		 * xxx(万元)的格式
		 * </pre>
		 */
		protected String unit;
		
		/**
		 * 数据项的类型
		 */
		protected JavaType attributeType = JavaType.NUMBER;
	
		protected boolean needPicture;
		
		public boolean isNeedPicture() {
			return needPicture;
		}

		public void setNeedPicture(boolean needPicture) {
			this.needPicture = needPicture;
		}

		@Override
		public void setJavaType(JavaType javaType) {
			this.attributeType = javaType;
		}
		
		@Override
		public String getTitle() {
			return codeName + title;
		}
		
		public void setUnit(String unit) {
			this.unit = unit;
		}
		
		public void setTooltip(String tooltip) {
			this.tooltip = tooltip;
		}
		
		public void setCodeName(String codeName) {
			this.codeName = codeName;
		}
		
		public String getCodeName() {
			return codeName;
		}
		
		public String getHeadTitle() {
			return headTitle;
		}
		
		public void setHeadTitle(String headTitle) {
			this.headTitle = headTitle;
		}
		
		@Override
		public JavaType getAttributeType() {
			return attributeType;
		}
	
		@Override
		public String getName() {
			return name;
		}
		@Override
		public String getcolumnName() {
			return codeName;
		}
		
		@Override
		public DatabaseType getDataType() {
			return attributeType.getDatabaseType();
		}
		
		class AttributeFieldElement extends AbstractFieldElement{
	
			public AttributeFieldElement(TableRuntimeMaster master, TableInstance tableSource, FieldMetadata fieldMetadata) {
				super(master, tableSource, fieldMetadata);
				setAlias(codeName);
			}
	
			@Override
			public void toSqlString(StringBuilder sqlBuilder, IdentifyTableBase targetTable) throws Exception{
				
				String atAlias = codeName + '_';
				sqlBuilder.append("(select ").append(atAlias).append(".C_VALUE from ").append(targetTable).append(' ').append(atAlias);
				sqlBuilder.append(" where ").append(atAlias).append(".C_OWNERID=").append(targetTable.getAlias()).append('.').append(tableMetadata.getMainField()).append(" and ");
				sqlBuilder.append(atAlias).append(".C_CODE='").append(name).append("' and ").append(atAlias).append(".C_DELETED=0 limit 0,1) as ").append(getAlias());
	
			}
		}
	
		@Override
		public FieldElement buildFieldElement(TableRuntimeMaster master, TableInstance tableSource) {
			return new AttributeFieldElement(master, tableSource, this);
		}
	
		@Override
		public boolean enabled() {
			return true;
		}
	}
}
